package site.xuqing.nobean.analysis;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import site.xuqing.nobean.obj.INonObject;
import site.xuqing.nobean.obj.NonObject;

/**
 * @author xuqing
 * @Description json解析类
 * @createTime 2022年01月19日 14:47:03
 */
public class AnalysisJson {
    /**
     * 解析Json 成 NonObject
     *
     * @param json 需要解析的json字符串
     * @param <T>  NonObject
     * @return NonObject
     */
    public <T extends INonObject> T analysisFromJson(String json) {
        try {
            Object obj = new JSONTokener(json).nextValue();
            NonObject nonObject = new NonObject();
            realAnalysisFromJson(null, obj, nonObject);
            return (T) nonObject;
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return null;
    }
    
    /**
     * 解析NonObject 成 JSON
     *
     * @param object NonObject
     * @return Json
     */
    public String analysisToJson(INonObject object) {
        JSONObject jsonObject = new JSONObject();
        realAnalysisToJson(object, jsonObject);
        return jsonObject.toString();
    }
    
    /**
     * 递归解析对象
     *
     * @param keys      key
     * @param objects   obj
     * @param nonObject {@link NonObject}
     */
    private void realAnalysisFromJson(String keys, Object objects, INonObject nonObject) {
        try {
            if (objects instanceof JSONObject) {
                JSONObject jsonObject = (JSONObject) objects;
                Iterator<?> iterator = jsonObject.keys();
                if (keys != null) {
                    NonObject objectNonObject = new NonObject();
                    nonObject.setObject(keys, objectNonObject);
                    while (iterator.hasNext()) {
                        String key = (String) iterator.next();
                        Object obj = jsonObject.get(key);
                        realAnalysisFromJson(key, obj, objectNonObject);
                    }
                } else {
                    while (iterator.hasNext()) {
                        String key = (String) iterator.next();
                        Object obj = jsonObject.get(key);
                        realAnalysisFromJson(key, obj, nonObject);
                    }
                }
            } else if (objects instanceof JSONArray) {
                JSONArray jsonArray = (JSONArray) objects;
                List<INonObject> nonObjects = new ArrayList<>();
                for (int i = 0; i < jsonArray.length(); i++) {
                    INonObject nonObj = new NonObject();
                    Object obj = jsonArray.get(i);
                    realAnalysisFromJson(null, obj, nonObj);
                    nonObjects.add(nonObj);
                }
                nonObject.setList(keys, nonObjects);
            } else {
                nonObject.setValue(keys, objects);
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 反解析INonObject对象成json
     *
     * @param nonObject  INonObject
     * @param jsonObject JSONObject
     */
    private void realAnalysisToJson(INonObject nonObject, JSONObject jsonObject) {
        try {
            Map<String, Object> fieldMap = nonObject.getFieldMap();
            if (fieldMap.size() > 0) {
                for (Map.Entry<String, Object> entry : fieldMap.entrySet()) {
                    String k = entry.getKey();
                    Object v = entry.getValue();
                    jsonObject.put(k, v);
                }
            }
            Map<String, INonObject> objectMap = nonObject.getObjectMap();
            if (objectMap.size() > 0) {
                for (Map.Entry<String, INonObject> entry : objectMap.entrySet()) {
                    String k = entry.getKey();
                    INonObject v = entry.getValue();
                    JSONObject childJsonObject = new JSONObject();
                    jsonObject.put(k, childJsonObject);
                    realAnalysisToJson(v, childJsonObject);
                }
            }
            Map<String, List<INonObject>> listMap = nonObject.getListMap();
            if (listMap.size() > 0) {
                for (Map.Entry<String, List<INonObject>> entry : listMap.entrySet()) {
                    String k = entry.getKey();
                    List<INonObject> v = entry.getValue();
                    JSONArray childJsonArray = new JSONArray();
                    for (INonObject iNonObject : v) {
                        JSONObject childJsonObject = new JSONObject();
                        childJsonArray.put(childJsonObject);
                        realAnalysisToJson(iNonObject, childJsonObject);
                    }
                    jsonObject.put(k, childJsonArray);
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}
